iOS 9 新特性

属性

1.宏

NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END之间的所有属性默认都是nonnull

例子:

1
2
3
4
5
6
7
8
NS_ASSUME_NONNULL_BEGIN
@interface Property : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSUInteger age;

@end
NS_ASSUME_NONNULL_END

2.属性修饰符

2.1 nonnull \ __nonnull

nonnull \ __nonnull : setter 和 getter 都不能为nil

1
2
@property (nonatomic, strong, nonnull) NSArray *names;
@property (nonatomic, strong) NSArray * __nonnull name;

但是仅仅是一个警告,而且仅限于直接赋值为nil的时候.
1

没有警告

1
2
3
Property *p = [[Property alloc]init];
NSString *nilString = nil;
p.name = nilString;

2.2 nullable \ __nullable

nullable \ __nullable : setter 和 getter 都可以为nil
默认情况下, 不加nullable, setter 和 getter 都是可以为nil
nullable更多的作用在于程序员之间的沟通交流(提醒同事某个属性可能是nil)

1
2
@property (nonatomic, strong, nullable) NSArray *names;
@property (nonatomic, strong) NSArray * __nullable names;

2.3 null_resettable

null_resettable : setter可以为nil, getter不可以为nil

1
@property (null_resettable, nonatomic, strong) NSArray *names;

注意:以上均是针对指针类型的属性
错误写法:

1
2
@property (nonatomic, assign, nullable) int age;
//Nullability specifier 'nullable' cannot be applied to non-pointer type 'int'

3. 泛型

1
2
@property (nonatomic, strong) NSMutableArray<NSString *> *names;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *books;

自定义泛型
ObjectType(可以自己定义,swift中常用T)是传入类型的 占位符,只能在 @interface 上定义(类声明、类扩展、Category),这个类型在 @interface 和 @end 区间的作用域有效,可以把它作为入参、出参、甚至内部 NSArray 属性的泛型类型,应该说一切都是符合预期的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@interface MYStack<ObjectType> : NSObject

@property (nonatomic, assign,readonly) NSInteger count;

- (void)push:(ObjectType)object;

- (ObjectType)pop;

@end

//使用
MYStack<NSString *> *stack = [[MYStack alloc]init];
[stack push:@"xxx"];
[stack pop];

我们还可以给 ObjectType 增加类型限制,比如:

1
2
@interface MYStack<ObjectType:NSObject> : NSObject
@end

4.自定义泛型时使用

协变性和逆变性 covariant contravariant
例子:NSArray
不指定泛型类型的 MYStack 可以和任意泛型类型转化,但指定了泛型类型后,两个不同类型间是不可以强转的,假如你希望主动控制转化关系,就需要使用泛型的协变性和逆变性修饰符了:
covariant - 协变性,子类型可以强转到父类型(里氏替换原则)
2
contravariant - 逆变性,父类型可以强转到子类型
3

5.__kindof

例子:

1
2
- (nullable __kindof UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath; 
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag;

意思是返回的类型是UITableViewCell或者它的子类均可,相对于id类型,可以减少我们进行再次强转